package com.link.base.base.performance.service;

import com.link.base.base.performance.dao.mybatis.mapper.ProjectBonusMapper;
import com.link.base.base.performance.model.Bonus;
import com.link.base.base.performance.model.ProjectBonus;
import com.link.base.base.performance.model.ProjectPartBonus;
import com.link.base.base.project.model.AcceptanceList;
import com.link.base.base.project.model.Comptype;
import com.link.base.base.project.service.AcceptanceListService;
import com.link.base.base.project.service.ComptypeService;
import com.link.base.core.basic.util.BigDecimalUtils;
import com.link.core.basic.dao.mapper.BasicMapper;
import com.link.core.basic.service.BasicServiceException;
import com.link.core.basic.service.BasicServiceImpl;
import com.link.core.basic.service.ServiceException;
import com.link.core.util.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;

/**
 * 项目奖金
 *
 * @author 王昊
 * @date 2021-04-08 13:17:18
 */
@Service
public class ProjectBonusServiceImpl extends BasicServiceImpl<ProjectBonus> implements ProjectBonusService {

    private static BigDecimal ZERO = new BigDecimal(0);

    @Resource
    private ProjectBonusMapper    projectBonusMapper;

    @Resource
    private ProjectPartBonusService projectPartBonusService;

    @Resource
    private BonusService bonusService;

    @Resource
    private AcceptanceListService acceptanceListService;

    @Resource
    private ComptypeService comptypeService;

    @Override
    public BasicMapper<ProjectBonus> getBasicMapper() {
        return projectBonusMapper;
    }

    /**
     * 项目奖金所有计算都在这里
     * @param entity
     * @throws Exception
     */
    @Override
    public void calculateBonus(ProjectBonus entity) throws Exception {
        //查询本行项目奖金对应的所有零件奖金行
        ProjectPartBonus querPart = new ProjectPartBonus();
        querPart.setProjectBonusId(entity.getId());
        List<ProjectPartBonus> projectPartBonuses = projectPartBonusService.queryAll(querPart);
        if (projectPartBonuses == null || projectPartBonuses.isEmpty()) {
            //本行项目奖金无对应零件奖金明细，请先维护零件奖金明细再进行奖金计算！
            throw new ServiceException("IYUBONUS-001");
        }

        BigDecimal projectCarPrice = ZERO;
        BigDecimal modChangeBonus = ZERO;
        BigDecimal partChangeBonus = ZERO;

        for (ProjectPartBonus projectPartBonus : projectPartBonuses) {
            BigDecimal acctPriceCarPrice = BigDecimalUtils.changeNullToZero(projectPartBonus.getAcctPriceCarPrice());
            BigDecimal partModChangeBonus = BigDecimalUtils.changeNullToZero(projectPartBonus.getModChangeBonus());
            BigDecimal smallPartChangeBonus = BigDecimalUtils.changeNullToZero(projectPartBonus.getPartChangeBonus());
            projectCarPrice = projectCarPrice.add(acctPriceCarPrice);
            modChangeBonus = modChangeBonus.add(partModChangeBonus);
            partChangeBonus = partChangeBonus.add(smallPartChangeBonus);
        }
        //均车价：自动生成，为项目零件奖金表中，所有选择的零件的均车价相加之和。零件均车价值来源：该项目ID关联的最后一轮报价的报价轮次ID的客户均车价。
        entity.setProjectCarPrice(projectCarPrice);

        //产品单价系数 x等于上述项目均车价 ，根据均车价区间分别赋值
        if (projectCarPrice.compareTo(new BigDecimal(1)) > -1 && projectCarPrice.compareTo(new BigDecimal(11)) == -1) {
            //1<=x<11 系数为0.2
            entity.setProdCoefficient(new BigDecimal(0.2));
        } else if (projectCarPrice.compareTo(new BigDecimal(11)) > -1 && projectCarPrice.compareTo(new BigDecimal(21)) == -1) {
            //11<=x<21 系数为0.4
            entity.setProdCoefficient(new BigDecimal(0.4));
        } else if (projectCarPrice.compareTo(new BigDecimal(21)) > -1 && projectCarPrice.compareTo(new BigDecimal(31)) == -1) {
            //21<=x<31 系数为0.6
            entity.setProdCoefficient(new BigDecimal(0.6));
        } else if (projectCarPrice.compareTo(new BigDecimal(31)) > -1 && projectCarPrice.compareTo(new BigDecimal(41)) == -1) {
            //31<=x<41 系数为0.8
            entity.setProdCoefficient(new BigDecimal(0.8));
        } else if (projectCarPrice.compareTo(new BigDecimal(41)) > -1 && projectCarPrice.compareTo(new BigDecimal(51)) == -1) {
            //41<=x<51 系数为1.0
            entity.setProdCoefficient(new BigDecimal(1.0));
        } else if (projectCarPrice.compareTo(new BigDecimal(51)) > -1 && projectCarPrice.compareTo(new BigDecimal(101)) == -1) {
            //51<=x<101 系数为2.0
            entity.setProdCoefficient(new BigDecimal(2.0));
        } else if (projectCarPrice.compareTo(new BigDecimal(101)) > -1 && projectCarPrice.compareTo(new BigDecimal(501)) == -1) {
            //101<=x<501 系数为3.0
            entity.setProdCoefficient(new BigDecimal(3.0));
        } else if (projectCarPrice.compareTo(new BigDecimal(501)) > -1 && projectCarPrice.compareTo(new BigDecimal(1001)) == -1) {
            //501<=x<1001 系数为4.0
            entity.setProdCoefficient(new BigDecimal(4.0));
        } else if (projectCarPrice.compareTo(new BigDecimal(1001)) > -1) {
            //1001<=x系数为5.0
            entity.setProdCoefficient(new BigDecimal(5.0));
        } else {
            //项目均车价计算值非法，请联系管理员！
            throw new ServiceException("IYUBONUS-002");
        }

        //项目奖金小计：
        //若项目的零件类型是塑料件，且项目毛利小于15%，此处赋值3000；
        //零件类型是金属件，且毛利小于18%，此处赋值3000
        //若项目毛利不满足上述要求，此时项目奖金小计=5000*零件难易度系数*客户重要度系数*产品单价系数。
        //若项目奖金小计计算得值大于50000，此处赋值50000。
        BigDecimal projectBonusSub = ZERO;
        BigDecimal partDiffDegree = BigDecimalUtils.changeNullToZero(entity.getPartDiffDegree());
        BigDecimal custImport = BigDecimalUtils.changeNullToZero(entity.getCustImport());
        BigDecimal prodCoefficient = entity.getProdCoefficient();
        BigDecimal projectGross = BigDecimalUtils.changeNullToZero(entity.getProjectGross());
        String compProperty = entity.getCompProperty() == null ? "badCompProperty" : entity.getCompProperty();
        if ("badCompProperty".equals(compProperty)) {
            //该项目未关联到零件属性，请联系管理员!
            throw new ServiceException("IYUBONUS-003");
        }
        if ("Plastics".equals(compProperty) && projectGross.compareTo(new BigDecimal(0.15)) == -1) {
            //塑料件&&项目毛利小于15%
            entity.setProjectBonusSub(new BigDecimal(3000));
        } else if ("Metals".equals(compProperty) && projectGross.compareTo(new BigDecimal(0.18)) == -1) {
            //金属件&&项目毛利小于18%
            entity.setProjectBonusSub(new BigDecimal(3000));
        } else {
            //项目奖金小计=5000*零件难易度系数*客户重要度系数*产品单价系数
            projectBonusSub = new BigDecimal(5000).multiply(partDiffDegree).multiply(custImport).multiply(prodCoefficient);
            if (projectBonusSub.compareTo(new BigDecimal(50000)) == 1) {
                //项目奖金小计计算得值大于50000，此处赋值50000。
                entity.setProjectBonusSub(new BigDecimal(50000));
            } else {
                entity.setProjectBonusSub(projectBonusSub);
            }
        }

        //模具设变奖金：所有项目零件奖金的模具设变奖励金额相加之和。值来源：项目零件奖金表的字段模具设变奖励金额。若计算值大于20000，则赋值20000。
        if (modChangeBonus.compareTo(new BigDecimal(20000)) == 1) {
            entity.setModChangeBonus(new BigDecimal(20000));
        } else {
            entity.setModChangeBonus(modChangeBonus);
        }

        //零件设变奖金：所有项目零件奖金的零件设变奖励金额相加之和。值来源：项目零件奖金表的字段零件设变奖励金额。若计算值大于20000，则赋值20000。
        if (partChangeBonus.compareTo(new BigDecimal(20000)) == 1) {
            entity.setPartChangeBonus(new BigDecimal(20000));
        } else {
            entity.setPartChangeBonus(partChangeBonus);
        }

        //导向性产品奖金：若该项目的零件的零件难易度系数为2，则导向性产品奖金=项目年度销售额/基础产值*10000。此奖金最大值为10000，若计算大于10000，此处赋值10000。
        // 若零件难易度系数不为2，则赋值0。
        BigDecimal leadProdPrize = ZERO;
        BigDecimal annualSales = BigDecimalUtils.changeNullToZero(entity.getAnnualSales());
        BigDecimal basedOutput = BigDecimalUtils.changeNullToZero(entity.getBasedOutput());
        if (partDiffDegree.equals(new BigDecimal(2))) {
            //导向性产品奖金=项目年度销售额/基础产值*10000
            leadProdPrize = annualSales.divide(basedOutput,2,BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(10000));
            if (leadProdPrize.compareTo(new BigDecimal(10000)) == 1) {
                entity.setLeadProdPrize(new BigDecimal(10000));
            } else {
                entity.setLeadProdPrize(leadProdPrize);
            }
        } else {
            entity.setLeadProdPrize(ZERO);
        }


        //额外奖金：若该项目零件类型为螺母板，则额外奖金=1000*数量。数量等于该项目奖金的项目零件奖金行数量。
        BigDecimal partNum = BigDecimal.valueOf(projectPartBonuses.size());
        if ("螺母板".equals(entity.getCompType())) {
            entity.setAddBonus(new BigDecimal(1000).multiply(partNum));
        } else {
            entity.setAddBonus(ZERO);
        }
        //奖金合计：项目奖金小计+新客户拓展奖+模具设变奖金+零件设变奖金+导向性产品奖金+额外奖金
        BigDecimal clientDevAward = BigDecimalUtils.changeNullToZero(entity.getClientDevAward());
        entity.setTotalBonuses(entity.getProjectBonusSub().add(clientDevAward).add(entity.getModChangeBonus())
                .add(entity.getPartChangeBonus()).add(entity.getLeadProdPrize()).add(entity.getAddBonus()));

        projectBonusMapper.update(entity);

        //年度奖金头字段：奖金总额 = 奖金合计之和
        //根据本行记录的头ID查询项目奖金记录（查询该年度计划的全部项目奖金） 加和奖金合计
        BigDecimal totalBonuses = ZERO;
        List<ProjectBonus> projectBonuses = projectBonusMapper.queryAll(entity);
        for (ProjectBonus projectBonus : projectBonuses) {
            BigDecimal smalltotalBonuses = BigDecimalUtils.changeNullToZero(projectBonus.getTotalBonuses());
            totalBonuses = totalBonuses.add(smalltotalBonuses);
        }

        //根据本行记录头ID查出头，set奖金总额
        Bonus querBonus = new Bonus();
        querBonus.setId(entity.getBonusID());
        Bonus bonus = bonusService.queryById(querBonus);
        if (bonus != null) {
            bonus.setTotalBonus(totalBonuses);
            bonusService.update(bonus);
        }

    }



    /**
     * 年度奖金明细表 拉平数据
     * @param entity
     * @return
     */
    @Override
    public List<ProjectBonus> annualBonusReport(ProjectBonus entity) throws Exception {
        return projectBonusMapper.annualBonusReportPage(entity);
    }

    /**
     * 新建保存
     * @param entity
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(ProjectBonus entity) throws Exception {
        /**
         * 基础校验
         * 计算
         */
        entity = computeAllPrice(entity);
        this.insert(entity);
        this.handlerProjectBonusLineSum(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handlerProjectBonusLineSum(ProjectBonus entity) throws Exception {
        ProjectBonus allTotalBonuse = this.selectSumByBonusId(entity);
        if (Objects.isNull(allTotalBonuse)) {
            throw new BasicServiceException("奖金合计明细记录不存在");
        }
        BigDecimal totalBonuses = allTotalBonuse.getAllTotalBonus();
        Bonus querBonus = new Bonus();
        querBonus.setId(entity.getBonusID());
        Bonus bonus = bonusService.queryById(querBonus);
        if (Objects.isNull(bonus)) {
            throw new BasicServiceException("年度奖金对象为空");
        }
        entity.setAllTotalBonus(totalBonuses);
        bonus.setTotalBonus(totalBonuses);
        bonusService.update(bonus);
    }


    /**
     * 新建保存
     * @param entity
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void renew(ProjectBonus entity) throws Exception {
        /**
         * 基础校验
         * 计算
         */
        entity = computeAllPrice(entity);
        this.update(entity);
        this.handlerProjectBonusLineSum(entity);
    }

    /**
     * 校验和计算合计
     * @param pb
     * @return
     */
    public ProjectBonus computeAllPrice(ProjectBonus pb) throws Exception {
        //根据本行记录头ID查出头，set奖金总额
        if (Objects.isNull(pb.getBonusID())) {
            throw new BasicServiceException("年度奖金id对象为空!");
        }
        Bonus querBonus = new Bonus();
        querBonus.setId(pb.getBonusID());
        Bonus bonus = bonusService.queryById(querBonus);
        if (Objects.isNull(bonus)) {
            throw new BasicServiceException("年度奖金对象为空!");
        }

        /**
         * 校验项目：项目承接单，并获取零件类型属性
         *
         */

        if (Objects.isNull(pb.getAcceptanceListId())) {
            throw new BasicServiceException("项目选择异常位空!");
        }
        AcceptanceList acceptanceList = acceptanceListService.queryById(pb.getAcceptanceListId());
        if (Objects.isNull(acceptanceList)) {
            throw new BasicServiceException("项目承接单不存在!");
        }
        Long compTypeId = pb.getCompTypeId();
        if (Objects.isNull(compTypeId)) {
            throw new BasicServiceException("零件类型必输!");
        }
        Comptype comptype = comptypeService.queryById(compTypeId);
        if (Objects.isNull(comptype)) {
            throw new BasicServiceException("零件类型对象不存在!");
        }
        String compProperty = comptype.getCompProperty();
//        String compProperty = acceptanceList.getCompProperty();
        if (StringUtils.isBlank(compProperty)) {
            throw new BasicServiceException("零件属性为空!");
        }

        /**
         * 当零件类型为导电系列: Conduct 的情况下,D≤30000,大于30000，自动锁定为30000；
         * 其他类型零件当D大于50000，自动锁定为50000；
         */

        BigDecimal basedOutput = pb.getBasedOutput(); // 基础产值
        if (Objects.isNull(basedOutput) || basedOutput.compareTo(BigDecimal.ZERO) == -1) {
            throw new BasicServiceException("基础产值为空，请检查！");
        }
        // 奖金小计 = 基础产值(头信息)*客户重要度系数*零件难易度系数*产品单价系数
        BigDecimal custImport = pb.getCustImport(); //车均价
        if (Objects.isNull(custImport) || custImport.compareTo(BigDecimal.ZERO) == -1) {
            throw new BasicServiceException("客户重要度系数必输！");
        }

        BigDecimal partDiffDegree = pb.getPartDiffDegree(); //零件难易度系数
        if (Objects.isNull(partDiffDegree) || partDiffDegree.compareTo(BigDecimal.ZERO) == -1) {
            throw new BasicServiceException("零件难易度系数必输！");
        }
        BigDecimal prodCoefficient = pb.getProdCoefficient(); // 产品单价系数
        if (Objects.isNull(prodCoefficient) || prodCoefficient.compareTo(BigDecimal.ZERO) == -1) {
            throw new BasicServiceException("产品单价系数必输或不能小于0！");
        }

        BigDecimal projectBonusSub = BigDecimalUtils.multiply(
                BigDecimalUtils.multiply(
                        BigDecimalUtils.multiply(basedOutput, custImport),
                        partDiffDegree),
                prodCoefficient);

        if (StringUtils.equals(compProperty,"Conduct")) {
            // 如果计算的金额大于3W，则重置为3W，其他正常
            if (projectBonusSub.compareTo(BigDecimal.valueOf(30000)) == 1) {
                projectBonusSub = BigDecimal.valueOf(30000);
            }
        } else {
            // 如果计算的金额大于3W，则重置为3W，其他正常
            if (projectBonusSub.compareTo(BigDecimal.valueOf(50000)) == 1) {
                projectBonusSub = BigDecimal.valueOf(50000);
            }
        }

        pb.setProjectBonusSub(projectBonusSub);
        // BigDecimal projectBonusSub = pb.getProjectBonusSub(); // 项目奖金小计

        // 总计=奖金小计+新客户拓展奖+模具设变奖金+零件设变奖金+导向性产品奖金+额外奖金
        BigDecimal clientDevAward = pb.getClientDevAward(); // 新客户拓展奖
        if (Objects.isNull(clientDevAward) || clientDevAward.compareTo(BigDecimal.ZERO) == -1) {
            throw new BasicServiceException("新客户拓展奖必输或不能小于0！");
        }
        BigDecimal modChangeBonus = pb.getModChangeBonus(); // 模具设变奖金
        if (Objects.isNull(modChangeBonus) || modChangeBonus.compareTo(BigDecimal.ZERO) == -1) {
            throw new BasicServiceException("模具设变奖金必输或不能小于0！");
        }
        BigDecimal partChangeBonus = pb.getPartChangeBonus(); // 零件设变奖金
        if (Objects.isNull(partChangeBonus) || partChangeBonus.compareTo(BigDecimal.ZERO) == -1) {
            throw new BasicServiceException("零件设变奖金必输或不能小于0！");
        }
        BigDecimal leadProdPrize = pb.getLeadProdPrize(); // 导向性产品奖金
        if (Objects.isNull(leadProdPrize) || leadProdPrize.compareTo(BigDecimal.ZERO) == -1) {
            throw new BasicServiceException("导向性产品奖金必输或不能小于0！");
        }
        BigDecimal addBonus = pb.getAddBonus(); // 额外奖金
        if (Objects.isNull(addBonus) || addBonus.compareTo(BigDecimal.ZERO) == -1) {
            throw new BasicServiceException("额外奖金必输或不能小于0！");
        }
        BigDecimal totalBonuses = BigDecimalUtils.add(
                BigDecimalUtils.add(
                        BigDecimalUtils.add(
                                BigDecimalUtils.add(
                                        BigDecimalUtils.add(projectBonusSub,clientDevAward), // 新客户拓展奖
                                        modChangeBonus), // 模具设变奖金
                                partChangeBonus), // 零件设变奖金
                        leadProdPrize), // 导向性产品奖金
                addBonus); // 额外奖金

        pb.setTotalBonuses(totalBonuses); // 奖金合计
        return pb;
    }


    /**
     * 汇总行的所有奖金合计
     * @param entity
     * @return
     * @throws Exception
     */
    @Override
    public ProjectBonus selectSumByBonusId(ProjectBonus entity) throws Exception {
        return projectBonusMapper.selectSumByBonusId(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteById(ProjectBonus entity) throws Exception {
        if (Objects.isNull(entity.getId())) {
            throw new BasicServiceException("删除id为空");
        }
        if (Objects.isNull(entity.getBonusID())) {
            throw new BasicServiceException("年度奖金ID为空");
        }
        super.deleteById(entity);
        /**
         * 刷新头行计算
         */
        ProjectBonus projectBonus = this.selectSumByBonusId(entity);
        BigDecimal allTotalBonus = projectBonus.getAllTotalBonus();
        Bonus bonus = bonusService.queryById(entity.getBonusID());
        bonus.setTotalBonus(allTotalBonus);
        bonusService.update(bonus);
    }
}
